/*
 * Copyright (c) 2007 empronix (http://www.empronix.com)
 * Author: Benedikt Sauter <sauter@empronix.com>
 * All rights reserved.
 *
 * Short descripton of file:
 *
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright 
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above 
 *     copyright notice, this list of conditions and the following 
 *     disclaimer in the documentation and/or other materials provided 
 *     with the distribution.
 *   * Neither the name of the FH Augsburg nor the names of its 
 *     contributors may be used to endorse or promote products derived 
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF USE, 
 * DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "common.h"
#include "protocol.h"
#include "io.h"

void io_parser(char *buf)
{

  switch(buf[0]){
    case CMD_IO_INIT_PORT:
      io_init_port((int)buf[2]);
    case CMD_IO_INIT_PIN:
      io_init_usb((int)buf[2]);
    break;
    case CMD_IO_PORT_DIRECTION_IN:
      io_set_port_direction_in((int)buf[2],(unsigned char)buf[3]);
    break;
    case CMD_IO_PORT_DIRECTION_OUT:
      io_set_port_direction_out_usb((int)buf[2],(unsigned char)buf[3]);
    break;
    case CMD_IO_PORT_DIRECTION_TRI:
      io_set_port_direction_tri((int)buf[2],(unsigned char)buf[3]);
    break;
    case CMD_IO_PIN_DIRECTION_IN:
      io_set_pin_direction_in_usb((int)buf[2]);
    break;
    case CMD_IO_PIN_DIRECTION_OUT:
      io_set_pin_direction_out_usb((int)buf[2]);
    break;
    case CMD_IO_PIN_DIRECTION_TRI:
      io_set_pin_direction_tri((int)buf[2]);
    break;
    case CMD_IO_PORT_SET:
      io_set_port((int)buf[2],(unsigned char)buf[3]);
    break;
    case CMD_IO_PORT_GET:
      io_get_port((int)buf[2]);
    break;
    case CMD_IO_PIN_SET:
      io_set_pin_usb((int)buf[2],(int)buf[3]);
    break;
    case CMD_IO_PIN_GET:
      io_get_pin_usb((int)buf[2]);
    break;
    default:
      answer[0]=buf[0];
      answer[1]=RSP_UNKOWN_CMD;
      answer[2]=0;
      CommandAnswer(3);
  }
}

int io_init(int pin)
{
  if((pin >= 1 && pin <= 19) || (pin >=26 && pin <=44) ){
    io_set_pin_direction_out(pin);
    return RSP_OK; 
  }
  return RSP_UNKOWN_PIN;
}

void io_init_usb(int pin)
{
  answer[0]=CMD_IO_INIT_PIN;
  answer[1]= (unsigned char)io_init(pin);
  answer[2]=0;

  CommandAnswer(3);
}

void io_init_port(int port){}

int io_set_pin_direction_out(int pin)
{
  if((pin >= 1 && pin <= 19) || (pin >=26 && pin <=44) ){
    octopus.ports[pin] = PIN_OUT;
    switch(pin){
      case 1:   OX_DDR1 |=(1<<OX_P1); break;
      case 2:   OX_DDR2 |=(1<<OX_P2); break;
      case 3:   OX_DDR3 |=(1<<OX_P3); break;
      case 4:   OX_DDR4 |=(1<<OX_P4); break;
      case 5:   OX_DDR5 |=(1<<OX_P5); break;
      case 6:   OX_DDR6 |=(1<<OX_P6); break;
      case 7:   OX_DDR7 |=(1<<OX_P7); break;
      case 8:   OX_DDR8 |=(1<<OX_P8); break;
      case 9:   OX_DDR9 |=(1<<OX_P9); break;
      case 10:   OX_DDR10 |=(1<<OX_P10); break;
      case 11:   OX_DDR11 |=(1<<OX_P11); break;
      case 12:   OX_DDR12 |=(1<<OX_P12); break;
      case 13:   OX_DDR13 |=(1<<OX_P13); break;
      case 14:   OX_DDR14 |=(1<<OX_P14); break;
      case 15:   OX_DDR15 |=(1<<OX_P15); break;
      case 16:   OX_DDR16 |=(1<<OX_P16); break;
      case 17:   OX_DDR17 |=(1<<OX_P17); break;
      case 18:   OX_DDR18 |=(1<<OX_P18); break;
      case 19:   OX_DDR19 |=(1<<OX_P19); break;
      
      case 26:   OX_DDR26 |=(1<<OX_P26); break;
      case 27:   OX_DDR27 |=(1<<OX_P27); break;
      case 28:   OX_DDR28 |=(1<<OX_P28); break;
      case 29:   OX_DDR29 |=(1<<OX_P29); break;
      case 30:   OX_DDR30 |=(1<<OX_P30); break;
      case 31:   OX_DDR31 |=(1<<OX_P31); break;
      case 32:   OX_DDR32 |=(1<<OX_P32); break;
      case 33:   OX_DDR33 |=(1<<OX_P33); break;
      case 34:   OX_DDR34 |=(1<<OX_P34); break;
      case 35:   OX_DDR35 |=(1<<OX_P35); break;
      case 36:   OX_DDR36 |=(1<<OX_P36); break;
      case 37:   OX_DDR37 |=(1<<OX_P37); break;
      case 38:   OX_DDR38 |=(1<<OX_P38); break;
      case 39:   OX_DDR39 |=(1<<OX_P39); break;
      case 40:   OX_DDR40 |=(1<<OX_P40); break;
      case 41:   OX_DDR41 |=(1<<OX_P41); break;
      case 42:   OX_DDR42 |=(1<<OX_P42); break;
      case 43:   OX_DDR43 |=(1<<OX_P43); break;
      case 44:   OX_DDR44 |=(1<<OX_P44); break;
      default:
	  return RSP_UNKOWN_PIN;
    }
    return RSP_OK;
  } else {
    return RSP_UNKOWN_PIN;
  }
}

void io_set_pin_direction_out_usb(int pin)
{
  answer[0]=CMD_IO_PIN_DIRECTION_OUT;
  answer[1]= (unsigned char)io_set_pin_direction_out(pin);
  answer[2]=0;
  
  CommandAnswer(3);
}

void io_set_pin_direction_in_usb(int pin)
{
  answer[0]=CMD_IO_PIN_DIRECTION_IN;
  answer[1]= (unsigned char)io_set_pin_direction_in(pin);
  answer[2]=0;
  
  CommandAnswer(3);
}

void io_set_pin_direction_tri_usb(int pin)
{
  answer[0]=CMD_IO_PIN_DIRECTION_TRI;
  answer[1]= (unsigned char)io_set_pin_direction_tri(pin);
  answer[2]=0;
  
  CommandAnswer(3);
}

int io_set_pin_direction_in(int pin)
{
  if((pin >= 1 && pin <= 19) || (pin >=26 && pin <=44) ){
    octopus.ports[pin] = PIN_IN;
    switch(pin){
      case 1:   OX_DDR1 &=~(1<<OX_P1); break;
      case 2:   OX_DDR2 &=~(1<<OX_P2); break;
      case 3:   OX_DDR3 &=~(1<<OX_P3); break;
      case 4:   OX_DDR4 &=~(1<<OX_P4); break;
      case 5:   OX_DDR5 &=~(1<<OX_P5); break;
      case 6:   OX_DDR6 &=~(1<<OX_P6); break;
      case 7:   OX_DDR7 &=~(1<<OX_P7); break;
      case 8:   OX_DDR8 &=~(1<<OX_P8); break;
      case 9:   OX_DDR9 &=~(1<<OX_P9); break;
      case 10:   OX_DDR10 &=~(1<<OX_P10); break;
      case 11:   OX_DDR11 &=~(1<<OX_P11); break;
      case 12:   OX_DDR12 &=~(1<<OX_P12); break;
      case 13:   OX_DDR13 &=~(1<<OX_P13); break;
      case 14:   OX_DDR14 &=~(1<<OX_P14); break;
      case 15:   OX_DDR15 &=~(1<<OX_P15); break;
      case 16:   OX_DDR16 &=~(1<<OX_P16); break;
      case 17:   OX_DDR17 &=~(1<<OX_P17); break;
      case 18:   OX_DDR18 &=~(1<<OX_P18); break;
      case 19:   OX_DDR19 &=~(1<<OX_P19); break;
      
      case 26:   OX_DDR26 &=~(1<<OX_P26); break;
      case 27:   OX_DDR27 &=~(1<<OX_P27); break;
      case 28:   OX_DDR28 &=~(1<<OX_P28); break;
      case 29:   OX_DDR29 &=~(1<<OX_P29); break;
      case 30:   OX_DDR30 &=~(1<<OX_P30); break;
      case 31:   OX_DDR31 &=~(1<<OX_P31); break;
      case 32:   OX_DDR32 &=~(1<<OX_P32); break;
      case 33:   OX_DDR33 &=~(1<<OX_P33); break;
      case 34:   OX_DDR34 &=~(1<<OX_P34); break;
      case 35:   OX_DDR35 &=~(1<<OX_P35); break;
      case 36:   OX_DDR36 &=~(1<<OX_P36); break;
      case 37:   OX_DDR37 &=~(1<<OX_P37); break;
      case 38:   OX_DDR38 &=~(1<<OX_P38); break;
      case 39:   OX_DDR39 &=~(1<<OX_P39); break;
      case 40:   OX_DDR40 &=~(1<<OX_P40); break;
      case 41:   OX_DDR41 &=~(1<<OX_P41); break;
      case 42:   OX_DDR42 &=~(1<<OX_P42); break;
      case 43:   OX_DDR43 &=~(1<<OX_P43); break;
      case 44:   OX_DDR44 &=~(1<<OX_P44); break;
      default:
	  return RSP_UNKOWN_PIN;
    }
    return RSP_OK;
  } else {
    return RSP_UNKOWN_PIN;
  }
}
int io_set_pin_direction_tri(int pin)
{
  if((pin >= 1 && pin <= 19) || (pin >=26 && pin <=44) ){
    octopus.ports[pin] = PIN_TRI;
    io_set_pin_direction_out(pin);
    io_set_pin(pin,1);
    return RSP_OK;
  } else {
    return RSP_UNKOWN_PIN;
  }
}

int io_set_port_direction_out(int port,unsigned char mask){return 0;}
int io_set_port_direction_in(int port, unsigned char mask){return 0;}
int io_set_port_direction_tri(int port, unsigned char mask){return 0;}

void io_set_port_direction_out_usb(int port,unsigned char mask){}
void io_set_port_direction_in_usb(int port, unsigned char mask){}
void io_set_port_direction_tri_usb(int port, unsigned char mask){}

void io_get_port(int port){}
void io_get_port_bulk(int port, int number){}

void io_set_port(int port, unsigned char value){}
void io_set_port_bulk(int port, int number, unsigned char * buf){}


void io_set_pin_usb(int pin, int value)
{
  answer[0]=CMD_IO_PIN_SET;
  answer[1]=(unsigned char)io_set_pin(pin,value);
  answer[2]=0;
  CommandAnswer(3);
}


int io_set_pin(int pin, int value)
{
  if(octopus.ports[pin] == PIN_OUT){
    switch(pin){
      case 1:  if(value) OX_PORT1 |=(1<<OX_P1); else OX_PORT1 &=~(1<<OX_P1); break;
      case 2:  if(value) OX_PORT2 |=(1<<OX_P2); else OX_PORT2 &=~(1<<OX_P2); break;
      case 3:  if(value) OX_PORT3 |=(1<<OX_P3); else OX_PORT3 &=~(1<<OX_P3); break;
      case 4:  if(value) OX_PORT4 |=(1<<OX_P4); else OX_PORT4 &=~(1<<OX_P4); break;
      case 5:  if(value) OX_PORT5 |=(1<<OX_P5); else OX_PORT5 &=~(1<<OX_P5); break;
      case 6:  if(value) OX_PORT6 |=(1<<OX_P6); else OX_PORT6 &=~(1<<OX_P6); break;
      case 7:  if(value) OX_PORT7 |=(1<<OX_P7); else OX_PORT7 &=~(1<<OX_P7); break;
      case 8:  if(value) OX_PORT8 |=(1<<OX_P8); else OX_PORT8 &=~(1<<OX_P8); break;
      case 9:  if(value) OX_PORT9 |=(1<<OX_P9); else OX_PORT9 &=~(1<<OX_P9); break;
      case 10:  if(value) OX_PORT10 |=(1<<OX_P10); else OX_PORT10 &=~(1<<OX_P10); break;
      case 11:  if(value) OX_PORT11 |=(1<<OX_P11); else OX_PORT11 &=~(1<<OX_P11); break;
      case 12:  if(value) OX_PORT12 |=(1<<OX_P12); else OX_PORT12 &=~(1<<OX_P12); break;
      case 13:  if(value) OX_PORT13 |=(1<<OX_P13); else OX_PORT13 &=~(1<<OX_P13); break;
      case 14:  if(value) OX_PORT14 |=(1<<OX_P14); else OX_PORT14 &=~(1<<OX_P14); break;
      case 15:  if(value) OX_PORT15 |=(1<<OX_P15); else OX_PORT15 &=~(1<<OX_P15); break;
      case 16:  if(value) OX_PORT16 |=(1<<OX_P16); else OX_PORT16 &=~(1<<OX_P16); break;
      case 17:  if(value) OX_PORT17 |=(1<<OX_P17); else OX_PORT17 &=~(1<<OX_P17); break;
      case 18:  if(value) OX_PORT18 |=(1<<OX_P18); else OX_PORT18 &=~(1<<OX_P18); break;
      case 19:  if(value) OX_PORT19 |=(1<<OX_P19); else OX_PORT19 &=~(1<<OX_P19); break;
      
      case 26:  if(value) OX_PORT26 |=(1<<OX_P26); else OX_PORT26 &=~(1<<OX_P26); break;
      case 27:  if(value) OX_PORT27 |=(1<<OX_P27); else OX_PORT27 &=~(1<<OX_P27); break;
      case 28:  if(value) OX_PORT28 |=(1<<OX_P28); else OX_PORT28 &=~(1<<OX_P28); break;
      case 29:  if(value) OX_PORT29 |=(1<<OX_P29); else OX_PORT29 &=~(1<<OX_P29); break;
      case 30:  if(value) OX_PORT30 |=(1<<OX_P30); else OX_PORT30 &=~(1<<OX_P30); break;
      case 31:  if(value) OX_PORT31 |=(1<<OX_P31); else OX_PORT31 &=~(1<<OX_P31); break;
      case 32:  if(value) OX_PORT32 |=(1<<OX_P32); else OX_PORT32 &=~(1<<OX_P32); break;
      case 33:  if(value) OX_PORT33 |=(1<<OX_P33); else OX_PORT33 &=~(1<<OX_P33); break;
      case 34:  if(value) OX_PORT34 |=(1<<OX_P34); else OX_PORT34 &=~(1<<OX_P34); break;
      case 35:  if(value) OX_PORT35 |=(1<<OX_P35); else OX_PORT35 &=~(1<<OX_P35); break;
      case 36:  if(value) OX_PORT36 |=(1<<OX_P36); else OX_PORT36 &=~(1<<OX_P36); break;
      case 37:  if(value) OX_PORT37 |=(1<<OX_P37); else OX_PORT37 &=~(1<<OX_P37); break;
      case 38:  if(value) OX_PORT38 |=(1<<OX_P38); else OX_PORT38 &=~(1<<OX_P38); break;
      case 39:  if(value) OX_PORT39 |=(1<<OX_P39); else OX_PORT39 &=~(1<<OX_P39); break;
      case 40:  if(value) OX_PORT40 |=(1<<OX_P40); else OX_PORT40 &=~(1<<OX_P40); break;
      case 41:  if(value) OX_PORT41 |=(1<<OX_P41); else OX_PORT41 &=~(1<<OX_P41); break;
      case 42:  if(value) OX_PORT42 |=(1<<OX_P42); else OX_PORT42 &=~(1<<OX_P42); break;
      case 43:  if(value) OX_PORT43 |=(1<<OX_P43); else OX_PORT43 &=~(1<<OX_P43); break;
      case 44:  if(value) OX_PORT44 |=(1<<OX_P44); else OX_PORT44 &=~(1<<OX_P44); break;
      default:
	  return RSP_UNKOWN_PIN;
    }

    return RSP_OK;
  } else {
    return RSP_WRONG_PIN_CONFIG;
  } 
}

void io_set_pin_bulk(int pin, int number, int * buf){}

void io_get_pin_usb(int pin)
{
  int value;
  answer[0]=CMD_IO_PIN_GET;
  answer[1]= (unsigned char)io_get_pin(pin,&value);
  //answer[2]=1;
  answer[2]=(unsigned char)value;
  
  CommandAnswer(4);
}

int io_get_pin(int pin, int *value)
{
  *value = 0;
  if(octopus.ports[pin] == PIN_IN){
      if(pin==17){
	if( OX_PIN17 &(1<<OX_P17)) *value=1; 
      }
      if(pin==16){
	if( OX_PIN16 &(1<<OX_P16)) *value=1; 
      }

  #if 0
    switch(pin){
      case 1:  if( OX_PIN1 &(1<<OX_P1)) *value=1; break;
      case 2:  if( OX_PIN2 &(1<<OX_P2)) *value=1; break;
      case 3:  if( OX_PIN3 &(1<<OX_P3)) *value=1; break;
      case 4:  if( OX_PIN4 &(1<<OX_P4)) *value=1; break;
      case 5:  if( OX_PIN5 &(1<<OX_P5)) *value=1; break;
      case 6:  if( OX_PIN6 &(1<<OX_P6)) *value=1; break;
      case 7:  if( OX_PIN7 &(1<<OX_P7)) *value=1; break;
      case 8:  if( OX_PIN8 &(1<<OX_P8)) *value=1; break;
      case 9:  if( OX_PIN9 &(1<<OX_P9)) *value=1; break;
      case 10:  if( OX_PIN10 &(1<<OX_P10)) *value=1; break;
      case 11:  if( OX_PIN11 &(1<<OX_P11)) *value=1; break;
      case 12:  if( OX_PIN12 &(1<<OX_P12)) *value=1; break;
      case 13:  if( OX_PIN13 &(1<<OX_P13)) *value=1; break;
      case 14:  if( OX_PIN14 &(1<<OX_P14)) *value=1; break;
      case 15:  if( OX_PIN15 &(1<<OX_P15)) *value=1; break;
      case 16:  if( OX_PIN16 &(1<<OX_P16)) *value=1; break;
      case 17:  if( OX_PIN17 &(1<<OX_P17)) *value=1; break;
      case 18:  if( OX_PIN18 &(1<<OX_P18)) *value=1; break;
      case 19:  if( OX_PIN19 &(1<<OX_P19)) *value=1; break;
      
      case 26:  if( OX_PIN26 &(1<<OX_P26)) *value=1; break;
      case 27:  if( OX_PIN27 &(1<<OX_P27)) *value=1; break;
      case 28:  if( OX_PIN28 &(1<<OX_P28)) *value=1; break;
      case 29:  if( OX_PIN29 &(1<<OX_P29)) *value=1; break;
      case 30:  if( OX_PIN30 &(1<<OX_P30)) *value=1; break;
      case 31:  if( OX_PIN31 &(1<<OX_P31)) *value=1; break;
      case 32:  if( OX_PIN32 &(1<<OX_P32)) *value=1; break;
      case 33:  if( OX_PIN33 &(1<<OX_P33)) *value=1; break;
      case 34:  if( OX_PIN34 &(1<<OX_P34)) *value=1; break;
      case 35:  if( OX_PIN35 &(1<<OX_P35)) *value=1; break;
      case 36:  if( OX_PIN36 &(1<<OX_P36)) *value=1; break;
      case 37:  if( OX_PIN37 &(1<<OX_P37)) *value=1; break;
      case 38:  if( OX_PIN38 &(1<<OX_P38)) *value=1; break;
      case 39:  if( OX_PIN39 &(1<<OX_P39)) *value=1; break;
      case 40:  if( OX_PIN40 &(1<<OX_P40)) *value=1; break;
      case 41:  if( OX_PIN41 &(1<<OX_P41)) *value=1; break;
      case 42:  if( OX_PIN42 &(1<<OX_P42)) *value=1; break;
      case 43:  if( OX_PIN43 &(1<<OX_P43)) *value=1; break;
      case 44:  if( OX_PIN44 &(1<<OX_P44)) *value=1; break;
      default:
	  return RSP_UNKOWN_PIN;
    }
    #endif
    return RSP_OK;
  } else {
    return RSP_WRONG_PIN_CONFIG;
  } 

}
void io_get_pin_bulk(int pin, int number){}


